//
//  MarksViewController.swift
//  Automobile
//
//  Created by erkebulan elzhan on 7/31/20.
//  Copyright © 2020 erkebulan elzhan. All rights reserved.
//

import UIKit
import SnapKit


// MARK: - Base

final class MarksViewController: UIViewController, Alertable {
    
    // MARK: - Outlets
    
    lazy private var tableView: UITableView = {
        let table = UITableView()
        table.delegate = self
        table.dataSource = self
        table.register(MarkaCell.self, forCellReuseIdentifier: "markaCell")
        table.backgroundColor = .white
        table.showsVerticalScrollIndicator = false
        table.tableFooterView = UIView()
        table.separatorInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
        return table
    }()
    
    lazy private var modeSelectView: RoundedSCView = {
        let segmentControlView = RoundedSCView()
        segmentControlView.updateItems(items: MarkaModelMode.allCases.map { $0.rawValue })
        return segmentControlView
    }()
    
    lazy private var submitButton: UIButton = {
        let button = UIButton()
        button.backgroundColor = .blueColor
        button.layer.cornerRadius = 15.0
        button.setTitle("Показать результаты", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .medium)
        return button
    }()
    
    private lazy var spinnerView = SpinnerView()
    
    // MARK: - Properties
    
    private lazy var viewModel: MarksViewModel = {
        let viewModel = MarksViewModel()
        viewModel.delegate = self
        return viewModel
    }()
    
    // MARK: - Actions
    
    @objc func showResults (sender: UIButton) {
        let mode = MarkaModelMode.allCases[modeSelectView.transportSelect.selectedSegmentIndex]
        viewModel.carData.mode = mode
        viewModel.carData.marka = viewModel.selectedMarka
        viewModel.carData.models = []
        
        if (viewModel.resultDelegate == nil) {
            let resultsVC = ResultsViewController()
            resultsVC.putMarkData(carData: viewModel.carData)
            self.navigationController?.pushViewController(resultsVC, animated: true)
        } else {
            let resultCar = CarFilter(marka: viewModel.selectedMarka, models: [])
            viewModel.resultDelegate?.goBack(data: resultCar, type: mode)
            self.navigationController?.popViewController(animated: true)
        }
    }
    
    @objc fileprivate func showModels (notification: NSNotification) {
        if let userInfo = notification.userInfo {
            guard let _selectedMarka: Marka = userInfo["marka"] as? Marka, let markaIcon = userInfo["icon"] as? UIImage? else {
                return
            }
            self.openModelsScreen(selectedMarka: _selectedMarka, icon: markaIcon)
        }
    }
    
    @objc private func goBack (sender: UIBarButtonItem) {
        if (viewModel.isCarCreate) {
            self.navigationController?.dismiss(animated: true, completion: nil)
        } else {
            self.navigationController?.popViewController(animated: true)
        }
    }
    
    @objc private func closeVC (sender: UIBarButtonItem) {
        self.navigationController?.dismiss(animated: true, completion: nil)
    }
    
    // MARK: - Init
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setUpNavBar()
        addSearchBar()
        setUpUI()
        viewModel.loadMarks()
        if (viewModel.isCarCreate) {
            self.handleSingleSelection()
        }
    }
    
    override func viewWillAppear(_ animated: Bool) {
        viewModel.selectedMarka = nil
        self.view.backgroundColor = .white
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(true)
        NotificationCenter.default.addObserver(self, selector: #selector(showModels), name: NSNotification.Name(rawValue: "showModels"), object: nil)
    }

    override func viewDidDisappear(_ animated: Bool) {
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "showModels"), object: nil)
    }
}

// MARK: - Search Configuration

extension MarksViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        if viewModel.lastSearchBarTxt != searchController.searchBar.text {
            viewModel.searchTask?.cancel()
            
            let task = DispatchWorkItem { [weak self] in
                if searchController.searchBar.text?.isEmpty ?? true {
                    self?.viewModel.loadMarks()
                } else {
                    self?.viewModel.loadMarks(query: searchController.searchBar.text!)
                }
            }
            viewModel.searchTask = task
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.75, execute: task)
        }
        viewModel.lastSearchBarTxt = searchController.searchBar.text ?? ""
    }
}


// MARK: - Main Methods

extension MarksViewController: ViewModelProtocol {
    
    func updateCities(cities: [City]?) {}
    
    func updateSpinner(showSpinner: Bool) {
        showSpinner ? spinnerView.startAnimating() : spinnerView.stopAnimating()
        view.isUserInteractionEnabled = !showSpinner
    }
    
    func didHappenError(error: RequestError) {
        self.alertError(error: error)
    }
    
    func updatePosts() {
        self.tableView.reloadData()
    }
}


// MARK: - Methods

extension MarksViewController {
    
    // MARK: - Public
    
    public func setProps (carData: CarData? = nil, resultDelegate: ResultsVCDelegate? = nil) {
        self.viewModel.carData = carData
        
        if let delegate = resultDelegate {
            self.viewModel.resultDelegate = delegate
        }
    }
    
    public func getCarData () -> CarData? {
        return self.viewModel.carData
    }
    
    fileprivate func openModelsScreen (selectedMarka: Marka?, icon: UIImage?) {
        let mode = MarkaModelMode.allCases[modeSelectView.transportSelect.selectedSegmentIndex]
        viewModel.selectedMarka = selectedMarka
        viewModel.carData.mode = mode
        viewModel.carData.marka = selectedMarka
        viewModel.carData.markaImg = icon
        let modelsVC = ModelsViewController()
        modelsVC.setProps(carData: viewModel.carData, resultDelegate: viewModel.resultDelegate)
        self.navigationController?.pushViewController(modelsVC, animated: true)
    }
}

// MARK:- Setup UI

extension MarksViewController {
    
    private func setUpUI () {
        view.backgroundColor = .white
        view.addSubview(tableView)
        view.addSubview(modeSelectView)
        view.addSubview(submitButton)
        view.addSubview(spinnerView)
        
        submitButton.snp.makeConstraints { (make) in
            make.leading.trailing.equalToSuperview().inset(16)
            make.bottom.equalTo(view.safeAreaLayoutGuide).offset(-16)
            make.height.equalTo(44)
        }
        
        modeSelectView.snp.makeConstraints { (make) in
            make.leading.trailing.equalToSuperview().inset(16)
            make.top.equalTo(view.safeAreaLayoutGuide).offset(8)
            make.height.equalTo(40)
        }
        
        spinnerView.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
            make.width.height.equalTo(50.0)
        }
        
        if (viewModel.resultDelegate != nil && viewModel.isCarCreate) {
            tableView.snp.makeConstraints { (make) in
                make.top.equalTo(view.safeAreaLayoutGuide).offset(16)
            }
            modeSelectView.removeFromSuperview()
        } else {
            tableView.snp.makeConstraints { (make) in
                make.top.equalTo(modeSelectView.snp.bottom).offset(16)
            }
        }
        
        tableView.snp.makeConstraints { (make) in
            make.leading.trailing.equalToSuperview().inset(16)
            make.bottom.equalTo(submitButton.snp.top).offset(-12)
        }
        
        submitButton.addTarget(self, action: #selector(showResults(sender:)), for: .touchUpInside)
    }
    
    private func setUpNavBar () {
        if (!viewModel.isCarCreate) {
            self.addBackIcon()
        }
        navigationController?.navigationBar.prefersLargeTitles = true
        navigationController?.navigationBar.backgroundColor = .white
        navigationItem.title = "Марки"
        navigationItem.hidesSearchBarWhenScrolling = false
        navigationItem.hidesBackButton = true
    }
    
    private func addBackIcon () {
        let backIcon = UIImage(named: "cancel")
        let backButton = UIBarButtonItem(image: backIcon, style: .plain, target: self, action: #selector(goBack(sender:)))
        backButton.tintColor = .greyColor
        navigationItem.leftBarButtonItem = backButton
    }
    
    private func addCloseIcon () {
        let closeBarBnt = UIBarButtonItem(image: UIImage(named: "dismiss"), style: .plain, target: self, action: #selector(closeVC))
        closeBarBnt.tintColor = .greyColor
        self.navigationItem.rightBarButtonItem = closeBarBnt
    }
    
    private func addSearchBar () {
        let searchController = UISearchController(searchResultsController: nil)
        searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
        definesPresentationContext = true
        self.navigationController?.navigationItem.largeTitleDisplayMode = .always
        searchController.searchBar.placeholder = "Поиск марки"
        self.navigationItem.searchController = searchController
    }
    
    private func getTableViewHeader (for section: Int) -> UIView {
        let view = UIView.init(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 32))
        view.backgroundColor = .white
        
        let titleLbl = UILabel()
        titleLbl.frame = view.frame
        titleLbl.font = UIFont.systemFont(ofSize: 18, weight: .bold)
        titleLbl.textColor = UIColor(red: 31/255, green: 45/255, blue: 61/255, alpha: 1)
        titleLbl.text = viewModel.filteredData[section].name
        
        view.addSubview(titleLbl)
        return view
    }
    
    // Car Select Mode
    
    private func handleSingleSelection () {
        self.addCloseIcon()
    }
}



// MARK: - UI Table View Configuration

extension MarksViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let marka = viewModel.filteredData[indexPath.section].items[indexPath.row]
        self.openModelsScreen(selectedMarka: marka, icon: (tableView.cellForRow(at: indexPath) as! MarkaCell).getIcon())
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "markaCell") as! MarkaCell
        cell.marka = viewModel.filteredData[indexPath.section].items[indexPath.row]
        cell.selectionStyle = .none
        cell.backgroundColor = .white
        return cell
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        self.getTableViewHeader(for: section)
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return viewModel.filteredData.count
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return viewModel.filteredData[section].items.count
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return viewModel.filteredData[section].name
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80.0
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        let offsetY = scrollView.contentOffset.y
        let contentHeight = scrollView.contentSize.height
        if offsetY > contentHeight - scrollView.frame.size.height {
            
            if viewModel.nextURL != nil {
                self.viewModel.loadMarks(pagination: true)
            }
        }
    }
}
